package com.cskaoyan.javase.oop3._3inner._5lambda._0introduction;

/**
 * lambda表达式的引入和基本使用
 *
 * Lambda 表达式是 JDK8 的一个新特性，可以取代接口的匿名内部类，写出更优雅的Java 代码。
 * 如果说匿名内部类实际上是局部内部类的更进一步，简化了局部内部类，那么Lambda就是匿名内部类更进一步，语法上更简洁了，代码更优雅了，是高端的玩法，是人上人的玩法。
 * 以上描述，主要说了三点:
 *      1.lambda表达式仍然是特殊的局部内部类,仍然写在局部位置,它仍然具有局部内部类的注意事项
 *      2.lambda表达式在取代匿名内部类对象时,只能取代接口的匿名内部类,类的匿名内部类取代不了.当然lambda表达式对接口是有特殊要求的,也不是什么接口都能用lambda表达式.
 *      3.lambda表达式是匿名内部类对象的更进一步,更简洁,那么Lambda表达式得到的就是某个接口的实现类对象
 *
 * Lambda表达式的使用前提: 需要一个接口,而且接口不是一个一般的接口,
 *      而是有且仅有一个必须要实现的抽象方法的接口,这种接口在Java中,称之为"功能接口"(FunctionalInterface)
 *      在语法上,可以用注解@FunctionalInterface,标记它,如果语法不报错,那么说明它就是一个功能接口.反之就不是
 *
 *      思考:
 *          1.功能接口中仅有一个方法吗?
 *              不是,java8中接口新增了默认方法和静态方法,它们都不需要子类实现
 *          2.功能接口中,仅有一个抽象方法吗?
 *              不是的,某些特殊的抽象方法,不需要子类实现.
 *              Java当中的每一个类都继承Object,所以每个对象都有Object类当中的实现方法
 *
 * 功能接口写好了,以后,我们就可以通过Lambda表达式的语法创建它的实现类对象
 * 语法:
 *      (形参列表) -> {
 *          // 重写方法的方法体
 *      };
 * 解释一下:
 *      ()表示功能接口中,那个必须要实现的抽象方法的形参列表.
 *      -> 它是lambda表达式运算符,读作"goes to"
 *      {
 *
 *      }
 *      表示功能接口中,被重写的抽象方法的,重写方法体
 *
 * 其实,当你看到这个语法后,那你就明白了,为什么lambda表达式需要的接口是一个功能接口呢?
 * 因为语法只能重写一个父接口中的方法
 * 而且lambda表达式创建的子类对象,无法新增自己的独有成员.
 *
 *在方法等局部位置，写上述语法后，肯定会报错。原因在于Java是强类型语言，任何变量都有它的数据类型，而直接写Lambda表达式语言，编译器是无从得知它的数据类型的——这个Lambda表达式创建了接口的子类对象，到底是哪个接口的子类对象呢?
 *
 * 所以我们需要帮助编译器，明确Lambda表达式所表示的对象的类型，这个过程称之为"Lambda表达式的类型推断"
 *
 * 推断需要额外信息,根据代码上下文完成类型推断,主要有三种方式:
 *      1.直接用父接口的引用接收
 *      2.不用引用接收,但是直接告诉编译器类型
 *      语法:
 *          ((父接口名字) lambda表达式).方法名(参数);
 *     语法必须直接调用方法
 *     3.根据方法完成类型推断.
 *          借助返回值类型
 *          借助形参类型
 * 以上,lambda表达式的基本使用,我们就学习完了.
 *
 * @since 15:40
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 局部位置写lambda表达式
        IA ib = () -> {
            System.out.println("hello world!");
        };
        ib.test();

        System.out.println(((IB) (int a) -> {
            System.out.println(a);
            return 1;
        }).test(666666));

        method().test();
        method(
                (int a, int b) -> {
                    return a + b;
                }
        );
    }

    public static IA method() {
        return () -> {
            System.out.println("我是仌!");
        };
    }

    public static void method(IC i) {
        System.out.println(i.add(10, 10));
    }
}

@FunctionalInterface
interface IC {
    int add(int a, int b);
}

@FunctionalInterface
interface IB {
    int test(int a);
}

@FunctionalInterface
interface IA {
    void test();
    /*boolean equals(Object o);

    default void testDefault() {
        System.out.println("xxx");
    }

    static void testStatic() {
        System.out.println("xxx");
    }*/
}

/*
class IAImpl implements IA{
    @Override
    public void test() {

    }
}
*/
